import logging
import os
from django.views.generic.list import ListView
from tracking.models import TrackRecordFutures
from tracking.models import TrackRecordForex, TrackingWeek, MonthYearLinks
from tracking.models import TrackRecordUploadForm
#from django.forms.models import ModelForm
from django.http import HttpResponseRedirect, HttpResponse
from django.views.generic.edit import UpdateView, DeleteView, CreateView
from django.shortcuts import render_to_response
from django.template.context import RequestContext
from settings import MEDIA_ROOT
from django.contrib.auth.decorators import login_required, permission_required
import re
from jrcmodel.models import CST, MyConstants
import time
from django.db.utils import IntegrityError
from decimal import Decimal
import calendar
from jrcshared.models import JrcPermission
from tracking.forms import YearMonthTextForm, TrackRecordForexForm, TrackRecordFuturesForm
import datetime

class CreateTrackRecordForexView(CreateView):
    model = TrackRecordForex
    form_class = TrackRecordForexForm

    def get_success_url(self):
        return "/tracking/forex/?year=%d&month=%d" % (self.object.date.year, self.object.date.month)
    
class CreateTrackRecordFuturesView(CreateView):
    model = TrackRecordFutures
    form_class = TrackRecordFuturesForm
    
    def get_success_url(self):
        return "/tracking/futures/?year=%d&month=%d" % (self.object.date.year, self.object.date.month)

class ListTrackRecordForex(ListView):
    model = TrackRecordForex
    template_name = "tracking/trackrecordforex_list.html"

    def get_context_data(self, **kwargs):
#        print TrackRecordFutures.objects.all()
        context = super(ListView, self).get_context_data(**kwargs)
        context["form"] = TrackRecordForexForm()
        return context

    def get_queryset(self, *args, **kwargs):
        context = super(ListView, self).get_queryset(*args, **kwargs)
        return context

class ListTrackRecordFutures(ListView):
    model = TrackRecordFutures
    template_name = "tracking/listtrackrecordfutures.html"
    
    def get_context_data(self, **kwargs):
        print TrackRecordFutures.objects.all()
        context = super(ListView, self).get_context_data(**kwargs)
        context["form"] = TrackRecordFuturesForm()
        return context

    def get_queryset(self, *args, **kwargs):
        context = super(ListView, self).get_queryset(*args, **kwargs)
        return context

class UpdateFuturesView(UpdateView):
    model = TrackRecordFutures
    template_name = "tracking/trackrecordfutures_form.html"
    success_url = "/tracking/"

class UpdateForexView(UpdateView):
    model = TrackRecordForex
    template_name = "trackrecordforex_form.html"
    success_url = "/tracking/forex/"

class DeleteTrackRecordFuturesView(DeleteView):
    model = TrackRecordFutures
    template_name = "tracking/trackrecordfutures_confirm_delete.html"
    success_url = "/tracking/"

class DeleteTrackRecordForexView(DeleteView):
    model = TrackRecordForex
    template_name = "tracking/trackrecordforex_confirm_delete.html"
    success_url = "/tracking/forex/"


@login_required
def get_create_futures(request):
    """
    Displays new Track record (Futures) form and saves it on Ajax POST
    """

    # Prepare initial date from request if any
    year = request.GET.get("year", datetime.datetime.now().year)
    month = request.GET.get("month", datetime.datetime.now().month)
    day = datetime.datetime.now().day
    sdate = "%s-%s-%d" % (year, month, datetime.datetime.now().day)

    if request.method == "POST":
        form = TrackRecordFuturesForm(request.POST)
        year = int(request.POST.get("date_year", datetime.datetime.now().year))
        month = int(request.POST.get("date_month", datetime.datetime.now().month))
        day = int(request.POST.get("date_day", datetime.datetime.now().day))
        sdate = "%s-%s-%d" % (year, month, day)
        dt = datetime.datetime.strptime(sdate, "%Y-%m-%d")

        if form.is_valid():
            form.save()
            print "Clearing cache..."
            # Assume that Track record (Futures) is saved and clear cache for this month
            TrackRecordFutures.clear_tracks_cache(year, month)
            # Return only text, it is Ajax-based
            return HttpResponse("<div class='msg_success'>Track record (Futures) is saved</div>")
        
    else:
        dt = datetime.datetime.strptime(sdate, "%Y-%m-%d")
        form = TrackRecordFuturesForm(initial = {"date": dt})


    return render_to_response(
                "tracking/getcreatefutures.html"
                , {
                   "form": form,
                   "dt": dt,
                   "month": month,
                   "days": range(1, 32)
                }
                , context_instance=RequestContext(request))

@login_required
def get_create_forex(request):
    """
    Displays new Track record (Forex) form and saves it on Ajax POST
    """

    # Prepare initial date from request if any
    year = request.GET.get("year", datetime.datetime.now().year)
    month = request.GET.get("month", datetime.datetime.now().month)
    day = datetime.datetime.now().day
    sdate = "%s-%s-%d" % (year, month, datetime.datetime.now().day)

    if request.method == "POST":
        year = int(request.POST.get("date_year", datetime.datetime.now().year))
        month = int(request.POST.get("date_month", datetime.datetime.now().month))
        day = int(request.POST.get("date_day", datetime.datetime.now().day))
        sdate = "%s-%s-%d" % (year, month, day)
        dt = datetime.datetime.strptime(sdate, "%Y-%m-%d")

        form = TrackRecordForexForm(request.POST)
        if form.is_valid():
            form.save()
            # Return only text, it is Ajax-based
            return HttpResponse("<div class='msg_success'>Track record (Forex) is saved</div>")
        
    else:
        dt = datetime.datetime.strptime(sdate, "%Y-%m-%d")
        form = TrackRecordForexForm(initial = {"date": dt})

    return render_to_response(
                "tracking/getcreateforex.html"
                , {
                   "form": form,
                   "dt": dt,
                  "month": month,
                  "days": range(1, 32)
                }
                , context_instance=RequestContext(request))


def get_csts_as_map():
    ar_csts = {}
    csts = CST.objects.all()
    for cst in csts:
        ar_csts[cst.name.lower()] = cst
    return ar_csts

@login_required
def import_forex_from_file(request):
    if request.method == "POST":
        form = TrackRecordUploadForm(request.POST, request.FILES)
        
        # Statistics from import
        total = 0
        imported = 0
        ar_csts = get_csts_as_map()
        print "CSTs ar map: %s" % ar_csts
        
        if form.is_valid():
            f = request.FILES["trackfile"]
            print f
            print f.name
            # Remove non-ascii symbols
            filename = re.sub("[^a-zA-Z0-9]", "_", f.name)
            filename = "%s%s" % (MEDIA_ROOT, filename)
            fp = open(filename, "wb+")
            for chunk in f.chunks():
                fp.write(chunk)
            fp.close()
            
            fp = open(filename, "r")
            s = ""
            for s in fp.readlines():
                total += 1
                ar = s.split('\t')
                if len(ar) > 9:
                    cst = None
                    cst_name = ar[1].lower()
                    if ar_csts.has_key(cst_name):
                        cst = ar_csts[cst_name]
                    else:
                        print "CST [%s] is not found!" % ar[1]
                    if cst != None:
#                        try:
                            tr = TrackRecordForex()
                            tr.status_id = MyConstants.STATUS_APPROVED
                            tm = time.strptime(ar[0], "%m/%d/%Y")
#                            print "Time from %s is %s" % (ar[0], tm)
                            tr.date = "%d-%d-%d" % (tm[0], tm[1], tm[2])
                            tr.cst_id = cst
                            tr.fee = int(ar[2])
                            print "Converting '%s', '%s' or '%s' to decimal..." % (ar[2], ar[3], ar[4])
#                            tr.min_mov = Decimal(ar[3])
                            tr.set_direction(ar[4])
                            tr.entry_value = ar[5]
                            tr.exit_value = ar[6]
                            tr.currency_xxx = ar[9].strip()
                            tr.currency_yyy = ar[10].strip()
#                            tr.point_value = int(ar[9])
#                            print tr
                            tr.save()
                            imported += 1
#                        except (ValueError, IntegrityError):
#                            print "Track record for Forex was not saved!"

        return HttpResponseRedirect("/tracking/forex/?total=%d&imported=%d" % (total, imported))

    return render_to_response(
                "tracking/importforexfromfile.html"
                , {
#                   "cst": cst
                   "form": TrackRecordUploadForm()
                }
                , context_instance=RequestContext(request))

@permission_required(JrcPermission.PET_CHANGE, "/accounts/denied/")
def import_futures_from_file(request):
    if request.method == "POST":
        form = TrackRecordUploadForm(request.POST, request.FILES)
        
        # Statistics from import
        total = 0
        imported = 0
        ar_csts = get_csts_as_map()
        print "CSTs ar map: %s" % ar_csts
        
        if form.is_valid():
            f = request.FILES["trackfile"]
            print f
            print f.name
            # Remove non-ascii symbols
            filename = re.sub("[^a-zA-Z0-9]", "_", f.name)
            filename = "%s%s" % (MEDIA_ROOT, filename)
            fp = open(filename, "wb+")
            for chunk in f.chunks():
                fp.write(chunk)
            fp.close()
            
            fp = open(filename, "r")
            s = ""
            line = 1
            for s in fp.readlines():
                total += 1
                ar = s.split('\t')
#                print "Rows in file is: %d" % len(ar)
                if len(ar) > 13:
#                    tm = time.strptime(ar[0], "%m/%d/%Y")
#                    print "Time from %s is %s" % (ar[0], tm)
                    cst = None
                    cst_name = ar[1].lower()
                    if ar_csts.has_key(cst_name):
                        cst = ar_csts[cst_name]
                    else:
                        print "CST [%s] is not found!" % ar[1]
                    if cst != None:
                        try:
                            tr = TrackRecordFutures()
                            tr.status_id = MyConstants.STATUS_APPROVED
                            tm = time.strptime(ar[0], "%m/%d/%Y")
    #                            print "Time from %s is %s" % (ar[0], tm)
                            tr.date = "%d-%d-%d" % (tm[0], tm[1], tm[2])
                            tr.cst_id = cst
                            tr.contracts_qnt = int(ar[2])
                            tr.set_direction(ar[4])
                            tr.entry_value = ar[5]
                            tr.exit_value = ar[6]
                            if len(ar[8].strip()) > 1:
                                tr.corrected_points = True
                            tr.point_value = int(ar[9])
                            print "Trading P/L from file: %s" % ar[13]
                            trading_pl = re.sub("[^\d\.]", "", ar[13])
                            if len(trading_pl) > 0:
                                tr.trading_profit_losses = Decimal(trading_pl)
                            else:
                                tr.trading_profit_losses = 0
#                            print tr
                            tr.save()
                            imported += 1
                        except (ValueError, IntegrityError):
                            print "Track record (Futures) on line #%d was not saved!" % line
                else:
                    print "Line #%d has less chunks %d that required (at least 14)!" % (line, len(ar))
                line += 1

            return HttpResponseRedirect("/tracking/?total=%d&imported=%d" % (total, imported))
    else:
        form = TrackRecordUploadForm()
    
    return render_to_response(
                "tracking/importfuturesfromfile.html"
                , {
#                   "cst": cst
                   "form": form
                }
                , context_instance=RequestContext(request))

#def create_track(request, tracktype):
#    try:
#        if tracktype == "forex":
#            form = TrackRecordForexForm(request.POST)
#        else:
#            form = TrackRecordFuturesForm(request.POST)
#            
#        if request.method == "POST":
#            if form.is_valid():
#                form.save()
#                return HttpResponseRedirect("/tracking/%s" % tracktype)
#    except ValueError:
#        return HttpResponseRedirect("/tracking/%s/?error" % tracktype)
#
#    return render_to_response("tracking/create")
    

def iso_weekday_name(weekday):
    """
    Returns name of weekday by its number, Monday is 1, Sunday is 7
    """
    ar_names = ["", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
    if weekday > 0 and weekday < len(ar_names):
        return ar_names[weekday]
    return "??%d??" % weekday

@login_required
def get_list_tracks_by_month(request, track_type = "futures"):
    ar_month = []

    month_year_link = MonthYearLinks("/tracking/%s/" % track_type, request)

    cal = calendar.Calendar()
    weeks = cal.monthdays2calendar(month_year_link.current_year, month_year_link.current_month)
    
    # Loop weeks in month
    for week in weeks:
#        print week
        tw = TrackingWeek(month_year_link.current_year, month_year_link.current_month)
#
        # Monday - Sunday
        for d in range(0, 7):
            month_date = week[d][0]
#            print "%d is %s" % (month_date, iso_weekday_name(week[d][1] + 1))
            if month_date:
                tw.set_for_weekday(d + 1, month_date)
            else:
                tw.set_for_weekday(d + 1, 0)
        ar_month.append(tw)
            
    print ar_month
#    print "Month start at %d, has %d days" % (first_month_weekday, total_days)
    
    if track_type == "forex":
        form = TrackRecordForexForm()
        month_stats = TrackRecordForex.calculate_month_stats(month_year_link.current_year, month_year_link.current_month)
#        print month_stats.fees_accumulated
    else:
        form = TrackRecordFuturesForm()
        month_stats = TrackRecordFutures().calculate_month_stats(month_year_link.current_year, month_year_link.current_month)
#        print "Contracts total: %d" % month_stats.contracts_qnt_total

    
    template_name = "tracking/get_trackrecord%s_list.html" % track_type
    return render_to_response(
                template_name
                , {
                   "month": ar_month
                   , "form": form
                   , "month_year_link": month_year_link
                   , "month_stats": month_stats
                }
                , context_instance=RequestContext(request))


@login_required
def list_tracks_by_month(request, track_type = "futures"):
    month_year_link = MonthYearLinks("/tracking/%s/" % track_type, request)

    # Pass to JS to disable charts for current month
    current_month = "false"
    if datetime.datetime.now().year == month_year_link.current_year and datetime.datetime.now().month == month_year_link.current_month:
        current_month = "true"
    
    template_name = "tracking/trackrecord%s_list.html" % track_type
    return render_to_response(
                template_name
                , {
                   "month_year_link": month_year_link
                   , "current_month": current_month
                }
                , context_instance=RequestContext(request))
    

@login_required
def import_text(request, tracktype):
    log = logging.getLogger(__name__)

    if tracktype == "forex":
        help_text = "Date  \\t  Market  \\t  Fee  \\t  Min.mov.  \\t  Dir.  \\t  Entry  \\t  Exit"
        min_chunks = 7
    else:
        help_text = "Date \\t CST \\t #Contr \\t Dir \\t Entry \\t Exit"
        min_chunks = 7
        
    
    if request.method == "POST":
        log.info("Start parsing Track records text parsing...")
        form = YearMonthTextForm(request.POST, request.FILES)
        
        if form.is_valid():
            nr = 0
            _ar_csts = get_csts_as_map()
            lines = form.cleaned_data["text"].split("\n")
            log.info("Parsing text of %s Track records type, containing %d lines" % (tracktype, len(lines)))
            tracks = []
            for l in lines:
                nr += 1
                if l.startswith("#"):
                    log.debug("Line %d is commented, skipping it" % nr)
#                    print "Line %d is commented, skipping it" % nr
                    continue
                
                ar = l.split("\t")
                # At least 14 cells + 3 optionals
                if len(ar) < min_chunks:
                    log.warning("Line %d has %d chunks. %d needed!" % (nr, len(ar), min_chunks))
#                    print "Line %d has %d chunks. %d needed!" % (nr, len(ar), min_chunks)
                    continue

                log.debug("Parsing: %s" % l)
                k = ar[1].lower()
                if _ar_csts.has_key(k):
                    try:
                        if tracktype == "forex":
                            tr = parse_array_to_forex_trackrecord(_ar_csts[k], ar)
                        else:
                            tr = parse_array_to_futures_trackrecord(_ar_csts[k], ar)
                        tracks.append(tr)
#                    print tr
                    except (ValueError, TypeError):
                        log.error("Error parsing Track record on line #%d!" % nr)
#                        print "Error parsing Track record on line #%d!" % nr
                else:
                    log.error("Could not find CST by [%s]" % ar[1])
#                    print "Could not find CST by [%s]" % ar[1]
            log.info("Storing %d Track records (%s) in session for preview..." % (len(tracks), tracktype))
#            print "Storing %d Track records (%s) in session for preview..." % (len(tracks), tracktype)
            request.session["tracking/%s/importtext" % tracktype] = tracks
            return HttpResponseRedirect("/tracking/%s/parsetext/?year=%s&month=%s" % (tracktype, request.POST.get("year"), request.POST.get("month")))
    else:
        form = YearMonthTextForm(initial = {"year": request.GET.get("year"), "month": request.GET.get("month")})
    return render_to_response(
                "tracking/importtext.html"
                , {
                   "form": form
                   , "help_text": help_text
                   , "tracktype": tracktype
                }
                , context_instance=RequestContext(request))

@login_required
def parse_text(request, tracktype):
    """
        Parses and imports Track records (Futures) to DB
    """

    log = logging.getLogger(__name__)

    # Check if we have parsed Track records from import
    track_session_key = "tracking/%s/importtext" % tracktype
    if not request.session.has_key(track_session_key):
        log.warning("No Track records session!")
        return HttpResponseRedirect("/tracking/%s/importtext/?nosession" % tracktype)
    
    if request.method == "POST":
        year = int(request.POST.get("year"))
        month = int(request.POST.get("month"))
        # Let's parse all
        if request.POST.get("confirm") == "1":
#            year = int(request.POST.get("year"))
#            month = int(request.POST.get("month"))
            start = "%d-%02d-01" % (year, month)
            if month == 12:
                end = "%d-01-01" % year + 1
            else:
                end = "%d-%d-01" % (year, month + 1)
            print "Deleting all [%s - %s]" % (start, end)

            if tracktype == "forex":
                log.warning("Deleting Track records (Forex), to import new, between (%s - %s]" % (start, end))
                TrackRecordForex.objects.filter(date__gte = start).filter(date__lt = end).delete()
            else:
                log.warning("Deleting Track records (Futures), to import new, between (%s - %s]" % (start, end))
                TrackRecordFutures.objects.filter(date__gte = start).filter(date__lt = end).delete()
            
            for tr in request.session[track_session_key]:
                tr.save()
            
            del request.session[track_session_key]
#            raise Exception("fasdf")
            return HttpResponseRedirect("/tracking/%s/?year=%d&month=%02d" % (tracktype, year, month))
        else:
            log.warning("Do not import Track records (%s) - delete of records for %d-%02d is not confirmed!" % (tracktype, year, month))
    else:
        year = request.GET.get("year")
        month = request.GET.get("month")
    
    return render_to_response(
                "tracking/parsetext.html"
                , {
                   "year": year
                   , "month": month
                   , "tracks": request.session[track_session_key]
                   , "tracktype": tracktype
#                   "form": form
                }
                , context_instance=RequestContext(request))

def parse_array_to_forex_trackrecord(cst, ar):
    """
    Parses array to TrackRecordForex object and returns it. None is returned in case of bad
    """

    ar_len = len(ar)
    tr = TrackRecordForex()
    
    tr = TrackRecordForex()
    tr.status_id = MyConstants.STATUS_APPROVED
    tm = MyConstants.try_convert_date_to_tm(ar[0])
#                            print "Time from %s is %s" % (ar[0], tm)
    tr.date = "%d-%d-%d" % (tm[0], tm[1], tm[2])
    tr.cst_id = cst
    # Fee is not mandatory
    if len(ar[2]) > 0:
        tr.fee = int(ar[2])
    else:
        tr.fee = 0
    print "Converting '%s', '%s' or '%s' to decimal..." % (ar[2], ar[3], ar[4])
#    tr.min_mov = MyConstants.convert_string_to_decimal(ar[3])
    tr.set_direction(ar[4])
    tr.entry_value = MyConstants.convert_string_to_decimal(ar[5])
    tr.exit_value = MyConstants.convert_string_to_decimal(ar[6])
#    tr.currency_xxx = ar[9].strip()
#    tr.currency_yyy = ar[10].strip()
    
    return tr


def parse_array_to_futures_trackrecord(cst, ar):
    """
    Parses array to TrackRecordFutures object and returns it. None is returned in case of bad
    """

#    date_fmt = "%d.%m.%Y"
    date_fmt = "%m/%d/%Y"
    ar_len = len(ar)

    tr = TrackRecordFutures()
    tr.status_id = MyConstants.STATUS_APPROVED

    tm = MyConstants.try_convert_date_to_tm(ar[0])
    print "Time from %s is %s" % (ar[0], tm)
    tr.date = "%d-%d-%d" % (tm[0], tm[1], tm[2])
    tr.cst_id = cst
    tr.contracts_qnt = int(ar[2])
    tr.set_direction(ar[4])
    tr.entry_value = MyConstants.convert_string_to_decimal(ar[5])
    tr.exit_value = MyConstants.convert_string_to_decimal(ar[6])
#    if len(ar[8].strip()) > 1:
#        tr.corrected_points = True
#    tr.point_value = int(ar[9])
#    print "Trading P/L from file: %s" % ar[15]
    
    tr.trading_profit_losses = 0
#    if ar_len > 15:
#        trading_pl = re.sub("[^\d\.]", "", ar[15])
#        if len(trading_pl) > 0:
#            tr.trading_profit_losses = Decimal(trading_pl)
#
#    if (ar_len > 16) and (len(ar[16]) > 0):
#        v = ar[16]
#        v = v.replace("\r", "")
#        v = v.split(".")[0]
#        v = v.replace(",", "")
##        print "Number of trades (string): [%s]" % v
#        if len(v) > 0:
#            tr.number_of_trades = int(v)
        
#    print "Number of trades: %d" % tr.number_of_trades
#    print "Trading P/L: %f" % tr.trading_profit_losses
    
    return tr
